package com.cmes.system.core.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cmes.core.Pagination;
import com.cmes.core.utils.Preconditions;
import com.cmes.jdbc.customquery.CustomQueryBO;
import com.cmes.jdbc.service.GenericService;
import com.cmes.system.core.constant.ErrorCode;
import com.cmes.system.core.entity.DictEntity;
import com.cmes.system.core.entity.DictItemEntity;
import com.cmes.system.core.repository.DictRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 字典管理
 *
 * @author Bruce.Gong
 * @since 1.0.0-SNAPSHOT
 */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
public class DictService extends GenericService<DictRepository, DictEntity> {

    private final DictItemService dictItemService;

    public Pagination<DictItemEntity> searchItems(CustomQueryBO bo) {
        return dictItemService.page(bo);
    }

    public List<DictItemEntity> listItems(String code) {
        return dictItemService.list(Wrappers.<DictItemEntity>lambdaQuery().eq(DictItemEntity::getCode, code));
    }

    public Map<String, String> mapItems(String code) {
        return listItems(code).stream().collect(Collectors.toMap(DictItemEntity::getItemKey, DictItemEntity::getItemValue));
    }

    // region 页面增删查改操作

    public void canAdd(DictEntity entity) {
        checkCode(entity.getCode());
    }

    public void canUpdate(Long id) {
        checkExist(getById(id));
    }

    public List<DictEntity> canDelete(List<Long> ids) {
        List<DictEntity> dbs = listByIds(ids);
        checkExist(dbs, ids.size());
        checkSystem(dbs);
        return dbs;
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delete(List<DictEntity> dbs) {
        Map<Long, String> map = dbs.stream().collect(Collectors.toMap(DictEntity::getId, DictEntity::getCode));
        deleteBatch(map.keySet());
        dictItemService.delete(Wrappers.<DictItemEntity>lambdaUpdate()
                .eq(DictItemEntity::getCode, map.values()));
    }

    private void checkExist(DictEntity db) {
        Preconditions.isNull(db, ErrorCode.DICT_NOT_EXISTS);
    }

    private void checkExist(List<DictEntity> dbs, int count) {
        Preconditions.isEmpty(dbs, ErrorCode.DICT_NOT_EXISTS);
        if (dbs.size() < count) {
            Preconditions.isTrue(true, ErrorCode.DICT_NOT_EXISTS);
        }
    }

    /**
     * 系统配置不能删除
     */
    private void checkSystem(List<DictEntity> dbs) {
        List<String> sysCodes = dbs.stream()
                .filter(v -> Boolean.TRUE.equals(v.getSys()))
                .map(DictEntity::getCode)
                .collect(Collectors.toList());
        Preconditions.notEmpty(sysCodes, ErrorCode.DICT_IS_SYS, sysCodes, "删除");
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param code code
     */
    private void checkCode(String code) {
        Preconditions.check(() -> exists(Wrappers.<DictEntity>lambdaQuery()
                .eq(DictEntity::getCode, code)), ErrorCode.DICT_CODE_EXISTS);
    }

    // endregion

    // region 页面操作明细，增删查改操作

    public void canAddItem(Long dictId, DictItemEntity entity) {
        DictEntity db = getById(dictId);
        checkExist(db);
        entity.setCode(db.getCode());
        checkItemKey(entity.getCode(), entity.getItemKey());
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void insertItem(DictItemEntity entity) {
        dictItemService.insert(entity);
    }

    public void canUpdateItem(Long id) {
        checkItemExist(dictItemService.getById(id));
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateItem(DictItemEntity entity) {
        dictItemService.update(entity);
    }

    public void canDeleteItem(List<Long> ids) {
        List<DictItemEntity> dbs = dictItemService.listByIds(ids);
        checkItemExist(dbs, ids.size());
    }

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteItems(List<Long> ids) {
        dictItemService.deleteBatch(ids);
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param code code
     */
    private void checkItemKey(String code, String itemKey) {
        Preconditions.check(() -> dictItemService.exists(Wrappers.<DictItemEntity>lambdaQuery()
                .eq(DictItemEntity::getCode, code)
                .eq(DictItemEntity::getItemKey, itemKey)),
                ErrorCode.DICT_ITEM_KEY_EXISTS);
    }

    private void checkItemExist(DictItemEntity db) {
        Preconditions.isNull(db, ErrorCode.DICT_ITEM_NOT_EXISTS);
    }

    private void checkItemExist(List<DictItemEntity> dbs, int count) {
        Preconditions.isEmpty(dbs, ErrorCode.DICT_ITEM_NOT_EXISTS);
        if (dbs.size() < count) {
            Preconditions.isTrue(true, ErrorCode.DICT_ITEM_NOT_EXISTS);
        }
    }

    // endregion
}
